#include "../include/misc.h"
#include <iostream>
#include <string>
#include <sstream>

#include <regex>
#include <uv.h>

hash_t hash_(char const* str)
{
	hash_t ret{basis};

	while(*str){
		ret ^= *str;
		ret *= prime;
		str++;
	}

	return ret;
}

hash_t hash_( char const *str , size_t len )
{
	hash_t ret{basis};
	size_t i = 0;
	while( i < len ){
		ret ^= str[ i ];
		ret *= prime;
		i ++;
	}

	return ret;
}

void log_base( bool enable , std::ostream& os , const std::string& str )
{
	if( enable )
		os << str;
}

void logln_base( bool enable , std::ostream& os , const std::string& str )
{
	if( enable )
		os << str << std::endl;
}

std::string GetUVError(int retcode)
{
	std::string err;
	err = uv_err_name(retcode);
	err +=":";
	err += uv_strerror(retcode);
	return std::move(err);
}

std::string do_url_match( const std::string& url , std::regex& reg)
{
	std::smatch rst;
	std::string ret;

	if( std::regex_match( url , rst , reg ) ){
		size_t c;
		c = rst.size(  );
		if( c > 1 ){//存在多个匹配，这个URL格式不正确
			ret.clear(  );
		}
		else if( c != 0 ){
			ret = rst.str( 0 );
		}
	}
	else{//字符串是否存匹配
		ret.clear(  );
	}

	return ret;
}

std::string GetURLProtocol( const std::string& url )
{
	std::regex reg( "(^|\\b)\\w+(?=://)" );

	return do_url_match( url , reg );
}

std::string GetURLHost( const std::string& url )
{
	std::regex reg( "(?:^|(://))(\\w|\\.)+(?=:|/|;|$)" );

	return do_url_match( url , reg );
}

std::string GetURLPath( const std::string& url )
{
	std::regex reg( "(?:\\/)(\\w|\\/)+(?=\\?|\\#|\\/|;|$)" );

	return do_url_match( url , reg );
}

std::string GetURLService( const std::string& url )
{
	std::regex reg( "(?:\\:)\\d+(?=\\?|\\#:|/|;|$)" );

	return do_url_match( url , reg );
}

std::string GetURLParam( const std::string& url )
{
	std::regex reg( "(?:;)\\w+(?=\\?|\\#:|/|;|$)" );

	return do_url_match( url , reg );
}

std::string GetURLQuery( const std::string& url )
{
	std::regex reg( "(?:\?)\\w+(?=\\?|\\#:|/|;|$)" );

	return do_url_match( url , reg );
}

std::string GetURLFragment( const std::string& url )
{
	std::regex reg( "(?:\\#)\\w+(?=\\?|\\#:|/|;|$)" );

	return do_url_match( url , reg );
}

std::string GetNopollError()
{
	std::string ret;

	return ret;
}

#if defined __DEBUG__
void dump( const char* data , size_t s )
{
	for( size_t i = 0; i < s; i ++ ){
		printf(" 0X%02X" , data[ i ]);
		if( i % 16 ) puts("\n");
	}
}

void dump_2( const char* data , size_t s )
{
	std::string str( data );
	printf("[RECV DATA] %s\n" , str.c_str() );
}
#endif

size_t str2hex( const std::string& str , uint8_t * data )
{
	if( data == nullptr ) return 0;
	uint32_t   tmp = 0;

	for( size_t i = 0 , j = 0; i < str.length(); i += 2 , j ++ ){
		std::string s = str.substr( i , 2 );
		std::stringstream ss;
		ss << s;
		ss >> std::hex >> tmp;
		data[ j ] = (uint8_t )(tmp & 0xff);
	}

	size_t ret = str.length() >> 1;
	if( str.length() & 1 ) ret ++;

	return ret;
}

size_t hex2str( const char * data , size_t len , std::string& str )
{
	if( data == nullptr ) return 0;

	for( size_t i = 0; i < len; i ++ ){
		uint8_t d = (uint8_t)data[ i ];

		std::stringstream ss;
		ss << std::hex << d;
		str += ss.str();
	}

	return len << 1;
}

bool str2hex4bit( const std::string& str , uint8_t * rst )
{
	// 
	if( str.empty() ) return false;
	if( rst == nullptr ) return false;

	bool ret = false;
	uint8_t * p = rst;
	size_t len = str.length();
	memset( p , 0 , len >> 1 );
	
	for( size_t i = 0 , j = 0; i < len - 1; i += 2 , j ++ ){
		char d = str.at( i );
		if( d > 0x40 ){
			p[ j ] = ( ( d & 0x0f ) + 9 ) << 4;		// 
		}else{
			p[ j ] = ( d & 0x0f  ) << 4;
		}

		d = str.at( i + 1 );

		if( d > 0x40 ){
			p[ j ] += ( ( d & 0x0f ) + 9 );			// 
		}else{
			p[ j ] += ( d & 0x0f );
		}
	}

	ret = true;
	return ret;
}